package com.refusea.commons.net

import com.refusea.commons.utils.Systems
import java.io.IOException
import java.net.Inet4Address
import java.net.InetAddress
import java.net.NetworkInterface
import java.net.ServerSocket
import java.util.Enumeration
import org.slf4j.Logger
import org.slf4j.LoggerFactory

/**
 * @author Zhang Yan
 * @date 2023-5-18
 **/
object LocalHost {

    private val log: Logger = LoggerFactory.getLogger(LocalHost::class.java)

    private val ipv4: Inet4Address? = get()

    private val hostAddress: String = ipv4?.hostAddress ?: "127.0.0.1"
    private val address: ByteArray = ipv4?.address ?: ByteArray(4)
    private val hostname: String = ipv4?.hostName ?: "LOCAL_HOST_NAME"

    // 以太网卡前缀
    private const val ETH: String = "eth"

    @JvmStatic
    fun getIpv4(): Inet4Address? {
        return ipv4
    }

    /** 获取ip, 默认 127.0.0.1 **/
    @JvmStatic
    fun getHostAddress(): String {
        return hostAddress
    }

    /** 获取主机名, 默认 LOCAL_HOST_NAME **/
    @JvmStatic
    fun getHostName(): String {
        return hostname
    }

    /** 获取 ip 地址 **/
    @JvmStatic
    fun getAddress(): ByteArray {
        return address
    }


    private fun get(): Inet4Address? {
        try {
            val networkInterfaces: Enumeration<NetworkInterface?> = NetworkInterface.getNetworkInterfaces()
            var networkInterface: NetworkInterface?
            var name: String
            var inetAddress: InetAddress
            var firstIpv4: Inet4Address? = null
            var ipv4: Inet4Address?
            while (networkInterfaces.hasMoreElements()) {
                networkInterface = networkInterfaces.nextElement()
                if (networkInterface == null || networkInterface.isLoopback) {
                    continue
                }
                name = networkInterface.name
                for (interfaceAddress in networkInterface.interfaceAddresses) {
                    if (interfaceAddress == null || interfaceAddress.networkPrefixLength == 32.toShort()) {
                        continue
                    }
                    inetAddress = interfaceAddress.address
                    if (inetAddress is Inet4Address) {
                        ipv4 = inetAddress
                        if (!Systems.IS_OS_LINUX || name.startsWith(ETH)) {
                            // linux 优先返回 eth*
                            return ipv4
                        }
                        if (firstIpv4 == null) {
                            firstIpv4 = ipv4
                        }
                    }
                }
            }
            return firstIpv4
        } catch (e: Exception) {
            log.error(e.message, e)
        }
        return null
    }

    /** 返回一个可用的端口, -1 表示失败 **/
    @JvmStatic
    fun availablePort(): Int {
        try {
            ServerSocket(0).use { socket -> return socket.localPort }
        } catch (e: IOException) {
            log.error(e.message, e)
        }
        return -1
    }
}
